package com.log4jviewer.ui.views;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.ViewPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.log4jviewer.domain.LogEvent;

/**
 * Class represents a View where detail information about selected log is displayed.
 * 
 * @author <a href="mailto:rd.ryly@gmail.com">Ruslan Diachenko</a>
 */
public class DetailLogView extends ViewPart implements ISelectionListener {

    public static final String ID = "log4jviewer.ui.views.DetailLogView";

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private Text levelField;

    private Text dateField;

    private Text categoryField;

    private Text fileNameField;

    private Text classNameField;

    private Text methodField;

    private Text lineNumberField;

    private Text ndcField;

    private Text throwableField;

    private Text messageField;

    @Override
    public void createPartControl(final Composite parent) {
        ScrolledComposite scrolledComposite = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);

        Group logFieldsGroup = new Group(scrolledComposite, SWT.NONE);
        logFieldsGroup.setText("Detail log info");
        GridLayout gridLayout = new GridLayout();
        gridLayout.verticalSpacing = 0;
        logFieldsGroup.setLayout(gridLayout);

        int textFieldStyle = SWT.NONE;
        levelField = buildLogInfoField(logFieldsGroup, LogFieldLabel.LEVEL.getName(), textFieldStyle);
        dateField = buildLogInfoField(logFieldsGroup, LogFieldLabel.DATE.getName(), textFieldStyle);
        categoryField = buildLogInfoField(logFieldsGroup, LogFieldLabel.CATEGORY.getName(), textFieldStyle);
        fileNameField = buildLogInfoField(logFieldsGroup, LogFieldLabel.FILE_NAME.getName(), textFieldStyle);
        classNameField = buildLogInfoField(logFieldsGroup, LogFieldLabel.CLASS_NAME.getName(), textFieldStyle);
        methodField = buildLogInfoField(logFieldsGroup, LogFieldLabel.METHOD_NAME.getName(), textFieldStyle);
        lineNumberField = buildLogInfoField(logFieldsGroup, LogFieldLabel.LINE_NUMBER.getName(), textFieldStyle);
        ndcField = buildLogInfoField(logFieldsGroup, LogFieldLabel.NDC.getName(), textFieldStyle);

        textFieldStyle = SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER;
        throwableField = buildLogInfoField(logFieldsGroup, LogFieldLabel.THROWABLE.getName(), textFieldStyle);
        messageField = buildLogInfoField(logFieldsGroup, LogFieldLabel.MESSAGE.getName(), textFieldStyle);
        logger.debug("Log info fields were built.");

        scrolledComposite.setContent(logFieldsGroup);
        scrolledComposite.setExpandHorizontal(true);
        scrolledComposite.setExpandVertical(true);
        scrolledComposite.setMinSize(logFieldsGroup.computeSize(SWT.DEFAULT, SWT.DEFAULT));

        getViewSite().getPage().addSelectionListener(this);
        logger.debug("Listener for DetailLogView was added.");
    }

    @Override
    public void setFocus() {
        // no code
    }

    private Text buildLogInfoField(final Group logFieldsGroup, final String labelName, final int textFieldStyle) {
        final Composite composite = new Composite(logFieldsGroup, SWT.NONE);
        GridLayout gridLayout = new GridLayout();
        gridLayout.marginHeight = 2;
        GridData compositeGridData = null;

        if (textFieldStyle == (SWT.NONE)) {
            gridLayout.numColumns = 2;
            compositeGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
        } else {
            compositeGridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        }
        composite.setLayout(gridLayout);
        composite.setLayoutData(compositeGridData);

        // Create log field name (label).
        Label label = new Label(composite, SWT.BEGINNING);
        label.setText(labelName);
        FontData fontData = label.getFont().getFontData()[0];
        Font font = new Font(composite.getDisplay(), new FontData(fontData.getName(), fontData.getHeight(), SWT.BOLD));
        label.setFont(font);

        // Create log field.
        Text field = new Text(composite, textFieldStyle);
        GridData fieldLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
        field.setLayoutData(fieldLayoutData);
        field.setEditable(false);
        field.setBackground(label.getBackground());

        return field;
    }

    @Override
    public void selectionChanged(final IWorkbenchPart part, final ISelection selection) {
        if (part instanceof LogView) {
            LogView logView = (LogView) part;
            int selectedItemIndex = logView.getTable().getSelectionIndex();

            if (selectedItemIndex >= 0) {
                LogEvent log = logView.getLogList().getFilteredLog(selectedItemIndex);
                levelField.setText(log.getLevel());
                dateField.setText(log.getDate());
                categoryField.setText(log.getCategoryName());
                fileNameField.setText(log.getFileName());
                classNameField.setText(log.getClassName());
                methodField.setText(log.getMethodName());
                lineNumberField.setText(log.getLineNumber());
                ndcField.setText(log.getNdc());
                throwableField.setText(log.getThrowableInfo());
                messageField.setText(log.getMessage());
            }
        }
    }

    @Override
    public void dispose() {
        super.dispose();
        getViewSite().getPage().removeSelectionListener(this);
        logger.debug("Listener for DetailLogView was removed.");
    }

    private static enum LogFieldLabel {
        LEVEL("Level:"),
        DATE("Data:"),
        CATEGORY("Category:"),
        FILE_NAME("File name:"),
        CLASS_NAME("Class name:"),
        METHOD_NAME("Method name:"),
        LINE_NUMBER("Line number:"),
        NDC("Ndc:"),
        THROWABLE("Throwable:"),
        MESSAGE("Message:");

        private String name;

        private LogFieldLabel(final String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}
